package com.yyks.cnbooking.dubbo.service;

import cn.hutool.core.lang.TypeReference;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.json.XML;
import com.yyks.cnbooking.dubbo.base.CNRequest;
import com.yyks.cnbooking.dubbo.base.CNResponse;
import com.yyks.cnbooking.dubbo.base.IdentityInfo;
import com.yyks.cnbooking.dubbo.config.CNBookingAPIProperties;
import com.yyks.cnbooking.dubbo.constants.CNBookConstant;
import com.yyks.cnbooking.dubbo.param.CbPreBookingCheckParam;
import com.yyks.cnbooking.dubbo.param.addresssearch.CbAddressSearchParam;
import com.yyks.cnbooking.dubbo.param.booking.CbBookingParam;
import com.yyks.cnbooking.dubbo.param.bookingcancel.CbOrderCancelParam;
import com.yyks.cnbooking.dubbo.param.hotel.CbHotelListSearchParam;
import com.yyks.cnbooking.dubbo.param.hotel.CbHotelSearchParam;
import com.yyks.cnbooking.dubbo.param.ordersearch.CbOrderSearchParam;
import com.yyks.cnbooking.dubbo.param.rateplansearch.CbRatePlanSearchParam;
import com.yyks.cnbooking.dubbo.param.roomsearch.CbRoomSearchParam;
import com.yyks.cnbooking.dubbo.result.addresssearch.CbAddressSearchData;
import com.yyks.cnbooking.dubbo.result.booking.CbBookingData;
import com.yyks.cnbooking.dubbo.result.bookingcancel.CbBookingCancelData;
import com.yyks.cnbooking.dubbo.result.hotellistsearch.CbHotelListSearchData;
import com.yyks.cnbooking.dubbo.result.hotelsearch.CbHotelSearchData;
import com.yyks.cnbooking.dubbo.result.ordersearch.CbOrderSearchData;
import com.yyks.cnbooking.dubbo.result.prebookingcheck.CbPreBookingCheckData;
import com.yyks.cnbooking.dubbo.result.rateplansearch.CbRatePlanSearchData;
import com.yyks.cnbooking.dubbo.result.roomsearch.CbRoomSearchData;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;

@Service
@RestController
@Slf4j
public class CNBookingServiceImpl implements CNBookingService {

    @Autowired
    private CNBookingAPIProperties cnBookingAPIProperties;

    private IdentityInfo identityInfo;

    @PostConstruct
    public void init() {
        identityInfo = new IdentityInfo(cnBookingAPIProperties.getAppId(), cnBookingAPIProperties.getSecurityKey(),
                cnBookingAPIProperties.getUserName(), cnBookingAPIProperties.getPassWord(),
                cnBookingAPIProperties.getSignature());
    }

    /**
     * 酒店查询
     *
     * @param param
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public CNResponse<CbHotelSearchData> hotelSearch(CbHotelSearchParam param) {
        try {
            CNRequest<CbHotelSearchParam> cnRequest = getCNRequest(param.getPageNo(), param.getPageSize(), param.getActionName());
            cnRequest.setSearchConditions(param);
            JSONObject jsonObject = sendPost(cnRequest);
            return JSONUtil.parseObj(jsonObject).toBean(new TypeReference<CNResponse<CbHotelSearchData>>() {
            });
        } catch (Exception e) {
            log.info("查询酒店信息异常");
            e.printStackTrace();
        }
        return new CNResponse();
    }

    /**
     * 酒店列表查询
     *
     * @param param
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public CNResponse<CbHotelListSearchData> hotelListSearch(CbHotelListSearchParam param) {
        try {
            CNRequest<CbHotelListSearchParam> cnRequest = getCNRequest(param.getPageNo(), param.getPageSize(), param.getActionName());
            cnRequest.setSearchConditions(param);
            JSONObject jsonObject = sendPost(cnRequest);
            return JSONUtil.parseObj(jsonObject).toBean(new TypeReference<CNResponse<CbHotelListSearchData>>() {
            });
        } catch (Exception e) {
            log.info("查询酒店列表信息异常");
            e.printStackTrace();
        }
        return new CNResponse();

    }

    /**
     * 预订前校验
     *
     * @param param
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public CNResponse<CbPreBookingCheckData> preBookingCheck(CbPreBookingCheckParam param) {
        try {
            CNRequest<CbPreBookingCheckParam> cnRequest = getCNRequest(null, null, param.getActionName());
            cnRequest.setSearchConditions(param);
            JSONObject jsonObject = sendPost(cnRequest);
            return JSONUtil.parseObj(jsonObject).toBean(new TypeReference<CNResponse<CbPreBookingCheckData>>() {
            });
        } catch (Exception e) {
            log.info("订单预订前校验异常");
            e.printStackTrace();
        }
        return new CNResponse();
    }

    /**
     * 订单搜索
     *
     * @param param
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public CNResponse<CbOrderSearchData> orderSearch(CbOrderSearchParam param) {
        try {
            CNRequest<CbOrderSearchParam> cnRequest = getCNRequest(null, null, param.getActionName());
            cnRequest.setSearchConditions(param);
            JSONObject jsonObject = sendPost(cnRequest);
            return JSONUtil.parseObj(jsonObject).toBean(new TypeReference<CNResponse<CbOrderSearchData>>() {
            });
        } catch (Exception e) {
            log.info("订单搜索异常");
            e.printStackTrace();
        }
        return new CNResponse();
    }

    /**
     * 预订下单
     *
     * @param param
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public CNResponse<CbBookingData> booking(CbBookingParam param) {
        try {
            CNRequest<CbBookingParam> cnRequest = getCNRequest(null, null, param.getActionName());
            cnRequest.setSearchConditions(param);
            JSONObject jsonObject = sendPost(cnRequest);
            return JSONUtil.parseObj(jsonObject).toBean(new TypeReference<CNResponse<CbBookingData>>() {
            });
        } catch (Exception e) {
            log.info("预订下单异常");
            e.printStackTrace();
        }
        return new CNResponse();
    }

    /**
     * 房间查询
     *
     * @param param
     * @return
     */
    @Override
    @PostMapping("/room/search")
    @SuppressWarnings("unchecked")
    public CNResponse<CbRoomSearchData> roomSearch(@RequestBody CbRoomSearchParam param) {
        try {
            CNRequest<CbRoomSearchParam> cnRequest = getCNRequest(param.getPageNo(), param.getPageSize(), param.getActionName());

            cnRequest.setSearchConditions(param);
            JSONObject jsonObject = sendPost(cnRequest);
            return JSONUtil.parseObj(jsonObject).toBean(new TypeReference<CNResponse<CbRoomSearchData>>() {
            });
        } catch (Exception e) {
            log.info("房间查询结果异常");
            e.printStackTrace();
        }
        return new CNResponse();
    }

    /**
     * 价格计划查询
     *
     * @param param
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public CNResponse<CbRatePlanSearchData> ratePlanSearch(CbRatePlanSearchParam param) {
        try {
            CNRequest<CbRatePlanSearchParam> cnRequest = getCNRequest(param.getPageNo(), param.getPageSize(), param.getActionName());
            cnRequest.setSearchConditions(param);
            JSONObject jsonObject = sendPost(cnRequest);
            return JSONUtil.parseObj(jsonObject).toBean(new TypeReference<CNResponse<CbRatePlanSearchData>>() {
            });
        } catch (Exception e) {
            log.info("价格计划查询信息异常");
            e.printStackTrace();
        }
        return new CNResponse();
    }

    /**
     * 订单取消
     *
     * @param param
     * @return
     */
    @Override
    @SuppressWarnings("unchecked")
    public CNResponse<CbBookingCancelData> bookingCancel(CbOrderCancelParam param) {
        try {
            CNRequest<CbOrderCancelParam> cnRequest = getCNRequest(null, null, param.getActionName());
            cnRequest.setSearchConditions(param);
            JSONObject jsonObject = sendPost(cnRequest);
            return JSONUtil.toBean(jsonObject, CNResponse.class);
        } catch (Exception e) {
            log.info("订单预订前校验异常");
            e.printStackTrace();
        }
        return new CNResponse();
    }

    @Override
    public CNResponse<CbAddressSearchData> addressSearch(CbAddressSearchParam param) {

        try {
            HttpRequest httpRequest = HttpUtil.createGet("http://202.104.101.32:8007/StaticInfoQuery.aspx" + "?ActionName="+param.getActionName()+
                    "&auth="+cnBookingAPIProperties.getAuth());
            HttpResponse execute = httpRequest.execute();
            String body = execute.body();
            body = body.substring(body.indexOf("<pre id=\"xmlPrview\" class=\"brush:xml;toolbar:false;\">")+
                            "<pre id=\"xmlPrview\" class=\"brush:xml;toolbar:false;\">".length(),
                    body.lastIndexOf("</pre>"));

            body = body.replaceAll("&lt;","<").replaceAll("&gt;",">")
                    .replaceAll("&quot;","\"");
            JSONObject jsonObject = XML.toJSONObject(body);
            jsonObject = (JSONObject) jsonObject.get(CNBookConstant.RESPONSE_TAG_NAME);
            return JSONUtil.parseObj(jsonObject).toBean(new TypeReference<CNResponse<CbAddressSearchData>>() {
            });
        } catch (Exception e) {
            log.info("订单预订前校验异常");
            e.printStackTrace();
        }
        return new CNResponse();
    }

    /**
     * 发送post请求
     *
     * @param cnRequest
     * @return
     */
    private JSONObject sendPost(CNRequest cnRequest) {
        String requestParam = XML.toXml(JSONUtil.parseObj(cnRequest), CNBookConstant.REQUEST_TAG_NAME);
        HttpRequest httpRequest = HttpUtil.createPost(cnBookingAPIProperties.getUrl());
        httpRequest.form(CNBookConstant.XML_REQUEST, requestParam);
        HttpResponse execute = httpRequest.contentType(ContentType.FORM_URLENCODED.toString()).execute();
        String body = execute.body();
        try {
            JSONObject jsonObject = XML.toJSONObject(body);
            jsonObject = (JSONObject) jsonObject.get(CNBookConstant.RESPONSE_TAG_NAME);
            return jsonObject;
        }catch (Exception e){
            log.error("body的内容为：{}",body);
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 公共请求参数封装
     *
     * @param pageNo
     * @param pageSize
     * @param actionName
     * @return
     */
    private CNRequest getCNRequest(Integer pageNo, Integer pageSize, String actionName) {
        CNRequest cnRequest = new CNRequest<>();
        if (null != pageSize) {
            cnRequest.getScrollingInfo().setPageItems(pageSize);
        }
        if (null != pageNo) {
            cnRequest.getScrollingInfo().setPageNo(pageNo);
        }
        cnRequest.setActionName(actionName);
        cnRequest.setIdentityInfo(identityInfo);
        return cnRequest;
    }
}
